﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Messaging;
using mal.WP7.Framework.Messages;
using mal.WP7.GoogleAnalytics.Business.GoogleApi;
using mal.WP7.GoogleAnalytics.Business.Repository;
using mal.WP7.GoogleAnalytics.Business.Resources;

namespace mal.WP7.GoogleAnalytics.ViewModels
{
    public class WebsitePageViewModel : ViewModelBase
    {
        #region Fields

        private string websiteId;
        private Website website;
        private bool daySelected;
        private bool weekSelected;
        private bool monthSelected;

        private bool isLoading;

        private Dictionary<object, double> values;
        private List<Statistic> stats;

        private double visits;
        private double visitors;
        private double pageViews;
        private double pagesViewPerVisit;
        private TimeSpan averageTimeOnSite;
        private double bounceRate;
        #endregion

        #region Construction / Destruction
        public WebsitePageViewModel(string websiteId)
        {
            Messenger.Default.Register<WebsitesAvailableMessage>(this, this.OnWebsitesAvailable);
            Messenger.Default.Register<WebsiteStatisticsAvailableMessage>(this, this.OnWebsiteStatisticsAvailable);

            this.websiteId = websiteId;
            this.Initialize();
        }
        #endregion

        #region enum, struct, class

        #endregion

        #region Properties
        public Website Website
        {
            get
            {
                return this.website;
            }

            set
            {
                this.website = value;
                RaisePropertyChanged("Website");
            }
        }

        public bool DaySelected
        {
            get
            {
                return this.daySelected;
            }

            set
            {
                if (this.Website != null)
                {
                    if (this.daySelected != value)
                    {
                        this.daySelected = value;
                        RaisePropertyChanged("DaySelected");

                        if (this.daySelected)
                        {
                            this.WeekSelected = false;
                            this.MonthSelected = false;
                            this.LoadDatas(Website.Days);
                        }
                    }
                }
            }
        }

        public bool WeekSelected
        {
            get
            {
                return this.weekSelected;
            }

            set
            {
                if (this.Website != null)
                {
                    if (this.weekSelected != value)
                    {
                        this.weekSelected = value;
                        RaisePropertyChanged("WeekSelected");

                        if (this.weekSelected)
                        {
                            this.DaySelected = false;
                            this.MonthSelected = false;
                            this.LoadDatas(Website.Weeks);
                        }
                    }
                }
            }
        }

        public bool MonthSelected
        {
            get
            {
                return this.monthSelected;
            }

            set
            {
                if (this.Website != null)
                {
                    if (this.monthSelected != value)
                    {
                        this.monthSelected = value;
                        RaisePropertyChanged("MonthSelected");

                        if (this.monthSelected)
                        {
                            this.DaySelected = false;
                            this.WeekSelected = false;
                            this.LoadDatas(Website.Months);
                        }
                    }
                }
            }
        }

        public bool IsLoading
        {
            get
            {
                return this.isLoading;
            }

            set
            {
                if (this.isLoading != value)
                {
                    this.isLoading = value;
                    RaisePropertyChanged("IsLoading");
                }
            }
        }

        public Dictionary<object, double> Values
        {
            get
            {
                return this.values;
            }

            set
            {
                if (this.values != value)
                {
                    this.values = value;
                    RaisePropertyChanged("Values");
                }
            }
        }

        public List<Statistic> Stats
        {
            get
            {
                return this.stats;
            }

            set
            {
                if (this.stats != value)
                {
                    this.stats = value;
                    RaisePropertyChanged("Stats");
                }
            }
        }

        public double BounceRate
        {
            get
            {
                return this.bounceRate;
            }

            set
            {
                if (this.bounceRate != value)
                {
                    this.bounceRate = value;
                    RaisePropertyChanged("BounceRate");
                }
            }
        }

        public TimeSpan AverageTimeOnSite
        {
            get
            {
                return this.averageTimeOnSite;
            }

            set
            {
                if (this.averageTimeOnSite != value)
                {
                    this.averageTimeOnSite = value;
                    RaisePropertyChanged("AverageTimeOnSite");
                }
            }
        }

        public double PagesViewPerVisit
        {
            get
            {
                return this.pagesViewPerVisit;
            }

            set
            {
                if (this.pagesViewPerVisit != value)
                {
                    this.pagesViewPerVisit = value;
                    RaisePropertyChanged("PagesViewPerVisit");
                }
            }
        }

        public double PageViews
        {
            get
            {
                return this.pageViews;
            }

            set
            {
                if (this.pageViews != value)
                {
                    this.pageViews = value;
                    RaisePropertyChanged("PageViews");
                }
            }
        }

        public double Visitors
        {
            get
            {
                return this.visitors;
            }

            set
            {
                if (this.visitors != value)
                {
                    this.visitors = value;
                    RaisePropertyChanged("Visitors");
                }
            }
        }

        public double Visits
        {
            get
            {
                return this.visits;
            }

            set
            {
                if (this.visits != value)
                {
                    this.visits = value;
                    RaisePropertyChanged("Visits");
                }
            }
        }
        #endregion

        #region Methods

        protected void LoadDatas(List<Statistic> stats)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                if (stats != null)
                {
                    this.IsLoading = false;

                    Dictionary<object, double> temp = new Dictionary<object, double>();

                    List<Statistic> visits = stats.Where(s => s.Metric == Metric.Visits).ToList();

                    for (int i = 0; i < visits.Count; i++)
                    {
                        Statistic stat = visits[i];
                        string date = string.Empty;

                        switch (stat.Dimension)
                        {
                            case Dimension.Day:
                            case Dimension.Week:
                                date = stat.StartDate.ToString("dd MMM");
                                break;

                            default:
                                date = stat.StartDate.ToString("MMM yyyy");
                                break;
                        }

                        if (!temp.ContainsKey(date))
                        {
                            temp.Add(date, stat.Value);
                        }
                    }

                    this.Values = temp;

                    this.Stats = stats;

                    this.CalculateStats();
                }
                else
                {
                    this.IsLoading = true;
                }
            });
        }

        private void Initialize()
        {
            if (WebsiteRepository.Instance.Websites != null)
            {
                this.website = WebsiteRepository.Instance.Websites.FirstOrDefault(w => w.Id == this.websiteId);

                if (this.website == null)
                {
                    MessageBox.Show(ResourceText.UnknownWebsiteErrorMessage
                                        , ResourceText.UnknownWebsiteErrorTitle
                                        , MessageBoxButton.OK);

                    Messenger.Default.Unregister<WebsitesAvailableMessage>(this, this.OnWebsitesAvailable);
                    Messenger.Default.Unregister<WebsiteStatisticsAvailableMessage>(this, this.OnWebsiteStatisticsAvailable);

                    NavigateMessage.Send(new Uri("/MainPage.xaml", UriKind.RelativeOrAbsolute));
                }

                this.DaySelected = true;
            }
        }

        private void CalculateStats()
        {
            this.Visitors = this.Stats.Where(s => s.Metric == Metric.Visitors).Sum(s => s.Value);
            this.Visits = this.Stats.Where(s => s.Metric == Metric.Visits).Sum(s => s.Value);
            this.PageViews = this.Stats.Where(s => s.Metric == Metric.Pageviews).Sum(s => s.Value);

            ////double averageTimeOnSiteInSeconds = this.Stats.Where(s => s.Metric == Metric.AvgTimeOnSite).Sum(s => s.Value) / this.Values.Count;
            ////int averageTimeOnSiteSeconds = (int)averageTimeOnSiteInSeconds;          
            ////TimeSpan averageTimeOnSite = new TimeSpan(0, 0, 0, (int)averageTimeOnSiteInSeconds);
            ////this.AverageTimeOnSite = averageTimeOnSite;

            ////this.BounceRate = this.Stats.Where(s => s.Metric == Metric.VisitBounceRate).Sum(s => s.Value) / this.Values.Count;
            this.PagesViewPerVisit = this.PageViews / this.Visits;
        }
        #endregion

        #region Events
        private void OnWebsitesAvailable(WebsitesAvailableMessage message)
        {
            if (message.Error != null)
            {
                this.IsLoading = false;

                MessageBox.Show(ResourceText.NetworkconnectionErrorMessage
                                    , ResourceText.NetworkconnectionErrorTitle
                                    , MessageBoxButton.OK);

            }
            else
            {
                this.Initialize();
            }
        }

        private void OnWebsiteStatisticsAvailable(WebsiteStatisticsAvailableMessage message)
        {
            if (this.website != null)
            {
                if (message.Error != null)
                {
                    this.IsLoading = false;

                    MessageBox.Show(ResourceText.NetworkconnectionErrorMessage
                                        , ResourceText.NetworkconnectionErrorTitle
                                        , MessageBoxButton.OK);
                }
                else
                {
                    if (this.DaySelected)
                    {
                        this.LoadDatas(message.Website.Days);
                    }
                    else if (this.WeekSelected)
                    {
                        this.LoadDatas(message.Website.Weeks);
                    }
                    else if (this.MonthSelected)
                    {
                        this.LoadDatas(message.Website.Months);
                    }
                }
            }
        }
        #endregion
    }
}
